function MainMapRenderer() {
	"use strict";
	// Stores canvas and context as static variables for indirection (browser independence) and performance
	this.mainMapCanvas = document.getElementById("mainMapCanvasId");
	this.mainMapCtx = this.mainMapCanvas.getContext('2d');
	//
	// Initializes map objects for later rendering
	this.onNewMapLoaded();
}

// Renders GUI
MainMapRenderer.prototype.render = function() {
	"use strict";
	// Update canvas size in case of window resize
	this.mainMapCanvas.width = window.innerWidth;
	this.mainMapCanvas.height = window.innerHeight;
	//
	// Translates according to cammera coordinates
	this.mainMapCtx.save();
	this.mainMapCtx.translate(-Game.gui.cammera.x, -Game.gui.cammera.y);
	//
	// Renders main map components
	this.renderMap(this.mainMapCtx);
	this.renderObjects(this.mainMapCtx);
	//
	this.mainMapCtx.restore();
};

// Renders main map
MainMapRenderer.prototype.renderMap = function(ctx) {
	"use strict";
	//
	this.renderMap_render(ctx, -Constants.TILE_WIDTH, -Constants.TILE_HEIGHT);
	this.renderMap_render(ctx, -Constants.TILE_WIDTH*1.5, -Constants.TILE_HEIGHT*1.5);
	
};

MainMapRenderer.prototype.renderMap_render = function(ctx, offsetX, offsetY) {
	var mapSizeX, mapSizeY, horizontalTiles, verticalTiles, i, j, cell, xo, yo, tx, ty;
	//
	mapSizeX = Game.model.map.cells.length;
	mapSizeY = Game.model.map.cells[0].length;
	//
	horizontalTiles = this.mainMapCanvas.width / Constants.TILE_WIDTH + 2;
	verticalTiles = this.mainMapCanvas.height / Constants.TILE_HEIGHT + 3;
	//
	xo = Game.gui.cammera.x + offsetX;
	for (i=0;i<horizontalTiles;i=i+1){
		//
		xo += Constants.TILE_WIDTH;
		//
		yo = Game.gui.cammera.y + offsetY;
		for (j=0;j<verticalTiles;j=j+1){
			//
			yo += Constants.TILE_HEIGHT;
			//
			// Convert from orthografic coordinates to isometric ones
			tx = Math.floor(CoordinatesUtil.getTileX(xo,yo));
			ty = Math.floor(CoordinatesUtil.getTileY(xo,yo));
			//
			if (tx>=0 && tx<mapSizeX && ty>=0 && ty<mapSizeY){
				cell = Game.model.map.cells[tx][ty];
				RenderUtil.render(ctx, cell.name, tx, ty, 0, 0.5);
			}
		}
	}
	// TODO: REMOVE - DEBUG info on busy cells map
	//for (i=0;i<mapSizeX;i=i+1){
	//	for (j=0;j<verticalTiles;j=j+1){
	//		if (Game.model.objectBag.busyCellsMap[i][j]!=0){
	//			RenderUtil.render(ctx, "soil_green_1", i, j, 0, 0.5);
	//		}
	//	}
	//}
}

// Renders objects in main map
MainMapRenderer.prototype.renderObjects = function(ctx) {
	"use strict";
	var i, o;
	//
	// Renders objects
	for (i = 0; i < Game.model.objectBag.objects.length; i=i+1) {
		o = Game.model.objectBag.objects[i];
		o.render(ctx);
		//
		// Render CENTER (TODO: Remove)
		ctx.fillStyle = '#ff0';
		ctx.fillRect(CoordinatesUtil.getX(o.x, o.y, 0, 0), CoordinatesUtil.getY(o.x, o.y, 0, 0), 2, 2);
	}
	//
	// Render ball (TODO: Remove)
	ctx.fillStyle = '#f00';
	ctx.fillRect(Game.model.x, Game.model.y, 5, 5);
};

// Notify a new map has been loaded
MainMapRenderer.prototype.onNewMapLoaded = function() {
	"use strict";
	// TODO: Dinamically load images for the map here, instead of having them statically defined in the html
	this.loadImage('scout_1', 'res/imgs/units/scout/scout_01.png');
	this.loadImage('scout_2', 'res/imgs/units/scout/scout_02.png');
	this.loadImage('scout_3', 'res/imgs/units/scout/scout_03.png');
	this.loadImage('scout_4', 'res/imgs/units/scout/scout_04.png');
	this.loadImage('scout_5', 'res/imgs/units/scout/scout_05.png');
	this.loadImage('scout_6', 'res/imgs/units/scout/scout_06.png');
	this.loadImage('scout_7', 'res/imgs/units/scout/scout_07.png');
	this.loadImage('scout_8', 'res/imgs/units/scout/scout_08.png');
	this.loadImage('scout_9', 'res/imgs/units/scout/scout_09.png');
	this.loadImage('scout_10', 'res/imgs/units/scout/scout_10.png');
	this.loadImage('scout_11', 'res/imgs/units/scout/scout_11.png');
	this.loadImage('scout_12', 'res/imgs/units/scout/scout_12.png');
	this.loadImage('scout_13', 'res/imgs/units/scout/scout_13.png');
	this.loadImage('scout_14', 'res/imgs/units/scout/scout_14.png');
	this.loadImage('scout_15', 'res/imgs/units/scout/scout_15.png');
	this.loadImage('scout_16', 'res/imgs/units/scout/scout_16.png');
	this.loadImage('scout_17', 'res/imgs/units/scout/scout_17.png');
	this.loadImage('scout_18', 'res/imgs/units/scout/scout_18.png');
	this.loadImage('scout_19', 'res/imgs/units/scout/scout_19.png');
	this.loadImage('scout_20', 'res/imgs/units/scout/scout_20.png');
	this.loadImage('scout_21', 'res/imgs/units/scout/scout_21.png');
	this.loadImage('scout_22', 'res/imgs/units/scout/scout_22.png');
	this.loadImage('scout_23', 'res/imgs/units/scout/scout_23.png');
	this.loadImage('scout_24', 'res/imgs/units/scout/scout_24.png');
	this.loadImage('scout_25', 'res/imgs/units/scout/scout_25.png');
	this.loadImage('scout_26', 'res/imgs/units/scout/scout_26.png');
	this.loadImage('scout_27', 'res/imgs/units/scout/scout_27.png');
	this.loadImage('scout_28', 'res/imgs/units/scout/scout_28.png');
	this.loadImage('scout_29', 'res/imgs/units/scout/scout_29.png');
	this.loadImage('scout_30', 'res/imgs/units/scout/scout_30.png');
	this.loadImage('scout_31', 'res/imgs/units/scout/scout_31.png');
	this.loadImage('scout_32', 'res/imgs/units/scout/scout_32.png');
	this.loadImage('selector1x1', 'res/imgs/units/shared/selector1x1.png');
	//
	this.loadImage('soil_1', 'res/imgs/soils/soil_1.png');
	this.loadImage('soil_2', 'res/imgs/soils/soil_2.png');
	this.loadImage('soil_green_1', 'res/imgs/soils/soil_green_1.png');
	this.loadImage('soil_green_2', 'res/imgs/soils/soil_green_2.png');
	//
	this.loadImage('grass_1', 'res/imgs/objs/grass_1.png');
	this.loadImage('grass_2', 'res/imgs/objs/grass_2.png');
	this.loadImage('log_1', 'res/imgs/objs/log_1.png');
	this.loadImage('tree_1', 'res/imgs/objs/tree_1.png');
	this.loadImage('tree_2', 'res/imgs/objs/tree_2.png');
	this.loadImage('tree_3', 'res/imgs/objs/tree_3.png');
};

// Notify a new map has been loaded
MainMapRenderer.prototype.loadImage = function(id, src) {
	"use strict";
	var img = document.createElement('img');
	img.id = id;
	img.src = src;
	img.hidden = true;
	document.body.appendChild(img);
};
